/* 
* jCountdown 1.3 jQuery Plugin
* Copyright 2011 Tom Ellis http://www.webmuse.co.uk
* Licensed under MIT License
* See http://www.webmuse.co.uk/license/
*/
(function ($) {

    $.fn.countdown = function (method /*,options*/) {

        var defaults = {
            date: (new Date()),
            updateTime: 1000,
            htmlTemplate: "%{d} <span class=\"cd-time\">days</span> %{h} <span class=\"cd-time\">hours</span> %{m} <span class=\"cd-time\">mins</span> %{s} <span class=\"cd-time\">sec</span>",
            minus: false,
            onChange: null,
            onComplete: null,
            onResume: null,
            onPause: null,
            leadingZero: false,
            offset: null,
            direction: 'down'
        },
			slice = [].slice,
			floor = Math.floor,
			msPerHour = 36E5,
			msPerDay = 864E5,
			rDate = /(%\{d\}|%\{h\}|%\{m\}|%\{s\})/g,
			rDays = /%\{d\}/,
			rHours = /%\{h\}/,
			rMins = /%\{m\}/,
			rSecs = /%\{s\}/,
			getTimezoneDate = function (offset) {

			    var hoursOffset = offset || 0,
					currentHours = 0,
					tempDate = new Date(),
					dateMS;

			    hoursOffset = hoursOffset * msPerHour;
			    currentHours = tempDate.getTime() - ((-tempDate.getTimezoneOffset() / 60) * msPerHour);
			    dateMS = tempDate.setTime(currentHours + hoursOffset);

			    return (new Date(dateMS));
			},
			timerFunc = function () {

			    var $this = this,
					template,
					todaysDate,
					countdownDate,
					timeLeft,
					e_daysLeft,
					daysLeft,
					e_hrsLeft,
					hrsLeft,
					minsLeft,
					e_minsleft,
					secLeft,
					time = "",
					settings = $this.data('jcdSettings');

			    if (!settings) {
			        return;
			    }

			    template = settings.htmlTemplate;

			    todaysDate = (settings.offset === null) ? new Date() : getTimezoneDate(settings.offset);

			    countdownDate = new Date(settings.date);

			    timeLeft = (settings.direction === 'down') ? countdownDate.getTime() - todaysDate.getTime() :
					todaysDate.getTime() - countdownDate.getTime();

			    e_daysLeft = timeLeft / msPerDay;
			    daysLeft = floor(e_daysLeft);
			    e_hrsLeft = (e_daysLeft - daysLeft) * 24;
			    hrsLeft = floor(e_hrsLeft);
			    minsLeft = floor((e_hrsLeft - hrsLeft) * 60);
			    e_minsleft = (e_hrsLeft - hrsLeft) * 60;
			    secLeft = floor((e_minsleft - minsLeft) * 60);

			    if (settings.leadingZero) {

			        if (daysLeft < 10) {
			            daysLeft = "0" + daysLeft;
			        }

			        if (hrsLeft < 10) {
			            hrsLeft = "0" + hrsLeft;
			        }

			        if (minsLeft < 10) {
			            minsLeft = "0" + minsLeft;
			        }

			        if (secLeft < 10) {
			            secLeft = "0" + secLeft;
			        }
			    }

			    if (settings.direction === 'down' && (todaysDate <= countdownDate || settings.minus)) {
			        time = template.replace(rDays, daysLeft).replace(rHours, hrsLeft).replace(rMins, minsLeft).replace(rSecs, secLeft);
			    } else if (settings.direction === 'up' && (countdownDate <= todaysDate || settings.minus)) {
			        time = template.replace(rDays, daysLeft).replace(rHours, hrsLeft).replace(rMins, minsLeft).replace(rSecs, secLeft);
			    } else {
			        time = template.replace(rDate, "00");
			        settings.hasCompleted = true;
			    }

			    $this.html(time);

			    $this.trigger('change', [settings]);

			    if (settings.hasCompleted) {

			        $this.trigger('complete.jcountdown');
			        window.clearInterval(settings.timer);
			    }
			},
			methods = {

			    init: function (options) {

			        var opts = $.extend({}, defaults, options),
						template;

			        template = opts.htmlTemplate;

			        return this.each(function () {
			            var $this = $(this),
							settings = {},
							todaysDate = (opts.offset === null) ? new Date() : getTimezoneDate(opts.offset),
							countdownDate = new Date(opts.date),
							timeLeft = (opts.direction === 'down') ? countdownDate.getTime() - todaysDate.getTime() :
								todaysDate.getTime() - countdownDate.getTime(),
							e_daysLeft = timeLeft / msPerDay,
							daysLeft = floor(e_daysLeft),
							e_hrsLeft = (e_daysLeft - daysLeft) * 24, //Gets remainder and * 24
							hrsLeft = floor(e_hrsLeft),
							minsLeft = floor((e_hrsLeft - hrsLeft) * 60),
							e_minsleft = (e_hrsLeft - hrsLeft) * 60, //Gets remainder and * 60
							secLeft = floor((e_minsleft - minsLeft) * 60),
							time = "",
							func;

			            if (opts.onChange) {
			                $this.bind("change.jcountdown", opts.onChange);
			            }

			            if (opts.onComplete) {
			                $this.bind("complete.jcountdown", opts.onComplete);
			            }

			            if (opts.onPause) {
			                $this.bind("pause.jcountdown", opts.onPause);
			            }

			            if (opts.onResume) {
			                $this.bind("resume.jcountdown", opts.onResume);
			            }

			            if (opts.leadingZero) {

			                if (daysLeft < 10) {
			                    daysLeft = "0" + daysLeft;
			                }

			                if (hrsLeft < 10) {
			                    hrsLeft = "0" + hrsLeft;
			                }

			                if (minsLeft < 10) {
			                    minsLeft = "0" + minsLeft;
			                }

			                if (secLeft < 10) {
			                    secLeft = "0" + secLeft;
			                }
			            }

			            settings.hasCompleted = false;

			            //Set initial time
			            if (opts.direction === 'down' && (todaysDate <= countdownDate || opts.minus)) {
			                time = template.replace(rDays, daysLeft).replace(rHours, hrsLeft).replace(rMins, minsLeft).replace(rSecs, secLeft);
			            } else if (opts.direction === 'up' && (countdownDate <= todaysDate || opts.minus)) {
			                time = template.replace(rDays, daysLeft).replace(rHours, hrsLeft).replace(rMins, minsLeft).replace(rSecs, secLeft);
			            } else {
			                time = template.replace(rDate, "00");
			                settings.hasCompleted = true;
			            }

			            //Store settings so they can be accessed later

			            settings.originalContent = $(this).html();
			            settings.date = opts.date;
			            settings.leadingZero = opts.leadingZero;
			            settings.updateTime = opts.updateTime;
			            settings.direction = opts.direction;
			            settings.template = opts.htmlTemplate;
			            settings.htmlTemplate = opts.htmlTemplate;
			            settings.minus = opts.minus;
			            settings.offset = opts.offset;
			            settings.onChange = opts.onChange;
			            settings.onComplete = opts.onComplete;
			            settings.onResume = opts.onResume;
			            settings.onPause = opts.onPause;

			            if (!settings.hasCompleted) {
			                func = $.proxy(timerFunc, $this);
			                settings.timer = window.setInterval(func, settings.updateTime);
			            }

			            $this.data('jcdSettings', settings);

			            $this.html(time);

			            if (settings.hasCompleted) {

			                $this.trigger('complete.jcountdown');
			                window.clearInterval(settings.timer);
			            }

			        });

			    },
			    changeSettings: function (options) {

			        //Like resume but with resetting/changing options

			        return this.each(function () {
			            var $this = $(this),
							settings,
							template,
							todaysDate,
							countdownDate,
							timeLeft,
							e_daysLeft,
							daysLeft,
							e_hrsLeft,
							hrsLeft,
							minsLeft,
							e_minsleft,
							secLeft,
							time = "",
							func;

			            if (!$this.data('jcdSettings')) {
			                return true;
			            }

			            settings = $.extend({}, $this.data('jcdSettings'), options);

			            template = settings.htmlTemplate;

			            todaysDate = (settings.offset === null) ? new Date() : getTimezoneDate(settings.offset);
			            countdownDate = new Date(settings.date);
			            timeLeft = (settings.direction === 'down') ? countdownDate.getTime() - todaysDate.getTime() :
							todaysDate.getTime() - countdownDate.getTime();
			            e_daysLeft = timeLeft / msPerDay;
			            daysLeft = floor(e_daysLeft);
			            e_hrsLeft = (e_daysLeft - daysLeft) * 24; //Gets remainder and * 24
			            hrsLeft = floor(e_hrsLeft);
			            minsLeft = floor((e_hrsLeft - hrsLeft) * 60);
			            e_minsleft = (e_hrsLeft - hrsLeft) * 60; //Gets remainder and * 60
			            secLeft = floor((e_minsleft - minsLeft) * 60);

			            $this.unbind('.jcountdown');

			            window.clearInterval(settings.timer);

			            if (settings.onChange) {
			                $this.bind('change.jcountdown', settings.onChange);
			            }

			            if (settings.onComplete) {
			                $this.bind('complete.jcountdown', settings.onComplete);
			            }

			            if (settings.onPause) {
			                $this.bind("pause.jcountdown", settings.onPause);
			            }

			            if (settings.onResume) {
			                $this.bind("resume.jcountdown", settings.onResume);
			            }

			            if (settings.direction === 'down' && (todaysDate <= countdownDate || settings.minus)) {
			                time = template.replace(rDays, daysLeft).replace(rHours, hrsLeft).replace(rMins, minsLeft).replace(rSecs, secLeft);
			            } else if (settings.direction === 'up' && (countdownDate <= todaysDate || settings.minus)) {
			                time = template.replace(rDays, daysLeft).replace(rHours, hrsLeft).replace(rMins, minsLeft).replace(rSecs, secLeft);
			            } else {
			                time = template.replace(rDate, "00");
			                settings.hasCompleted = true;
			            }

			            func = $.proxy(timerFunc, $this);

			            settings.timer = window.setInterval(func, settings.updateTime);

			            $this.data('jcdSettings', settings);

			            if (settings.hasCompleted) {
			                $this.trigger('complete.jcountdown');
			                window.clearInterval(settings.timer);
			            }

			        });

			    },
			    resume: function () {

			        return this.each(function () {
			            var $this = $(this),
							settings,
							template,
							func,
							todaysDate,
							countdownDate,
							timeLeft,
							e_daysLeft,
							daysLeft,
							e_hrsLeft,
							hrsLeft,
							minsLeft,
							e_minsleft,
							secLeft,
							time = "";

			            settings = $this.data('jcdSettings');

			            if (!settings) {
			                return true;
			            }

			            func = $.proxy(timerFunc, $this);

			            template = settings.htmlTemplate;

			            todaysDate = (settings.offset === null) ? new Date() : getTimezoneDate(settings.offset);
			            countdownDate = new Date(settings.date);
			            timeLeft = (settings.direction === 'down') ? countdownDate.getTime() - todaysDate.getTime() :
							todaysDate.getTime() - countdownDate.getTime();
			            e_daysLeft = timeLeft / msPerDay;
			            daysLeft = floor(e_daysLeft);
			            e_hrsLeft = (e_daysLeft - daysLeft) * 24;
			            hrsLeft = floor(e_hrsLeft);
			            minsLeft = floor((e_hrsLeft - hrsLeft) * 60);
			            e_minsleft = (e_hrsLeft - hrsLeft) * 60;
			            secLeft = floor((e_minsleft - minsLeft) * 60);

			            if (settings.direction === 'down' && (todaysDate <= countdownDate || settings.minus)) {
			                time = template.replace(rDays, daysLeft).replace(rHours, hrsLeft).replace(rMins, minsLeft).replace(rSecs, secLeft);
			            } else if (settings.direction === 'up' && (countdownDate <= todaysDate || settings.minus)) {
			                time = template.replace(rDays, daysLeft).replace(rHours, hrsLeft).replace(rMins, minsLeft).replace(rSecs, secLeft);
			            } else {
			                time = template.replace(rDate, "00");
			                settings.hasCompleted = true;
			            }

			            settings.timer = window.setInterval(func, settings.updateTime);

			            $this.data('jcdSettings', settings);

			            $this.trigger('resume.jcountdown');

			            $this.html(time).trigger('change.jcountdown');

			            if (settings.hasCompleted) {

			                $this.trigger('complete.jcountdown');
			                window.clearInterval(settings.timer);
			            }
			        });
			    },
			    pause: function () {

			        return this.each(function () {
			            var $this = $(this),
							settings = $.data($this[0], 'jcdSettings');

			            if (!settings) {
			                return true;
			            }

			            $this.trigger('pause.jcountdown');
			            window.clearInterval(settings.timer);
			        });
			    },
			    complete: function () {

			        return this.each(function () {
			            var $this = $(this),
							settings = $this.data('jcdSettings');

			            if (!settings) {
			                return true;
			            }

			            window.clearInterval(settings.timer);
			            settings.hasCompleted = true;

			            $this.data('jcdSettings', settings);
			            $this.trigger('complete.jcountdown');
			        });
			    },
			    destroy: function () {

			        return this.each(function () {
			            var $this = $(this),
							settings;

			            settings = $this.data('jcdSettings');

			            if (!settings) {
			                return true;
			            }

			            $this.unbind('.jcountdown');
			            $this.html(settings.originalContent);
			            $this.removeData('jcdSettings');
			        });
			    },
			    getSettings: function (name) {

			        var settings,
						$this = $(this[0]);

			        settings = $this.data('jcdSettings');

			        if (!settings) {
			            return undefined;
			        }

			        if (name) {

			            if (settings[name]) {
			                return settings[name];
			            }
			            return undefined;
			        }

			        return settings;
			    }
			};

        if (methods[method]) {

            return methods[method].apply(this, slice.call(arguments, 1));

        } else if ($.type(method) === 'object' || !method) {

            return methods.init.apply(this, arguments);
        } else {

            $.error('Method ' + method + ' does not exist in the jCountdown Plugin');
        }
    };

})(jQuery);